package client.gui.interfaces.component;

import java.awt.*;
import java.util.*;

import client.gui.interfaces.Action;

@SuppressWarnings("serial")
public abstract class Component extends Rectangle {
	
	public enum ActionType {
		MOUSE_CLICK, MOUSE_MOVE, MOUSE_ENTER, MOUSE_EXIT, MOUSE_PRESS, MOUSE_RELEASE
	}
	
	protected ArrayList<Component> children = new ArrayList<Component>();
	protected Container parent;
	protected HashMap<ActionType, Action> actionEvents = new HashMap<ActionType, Action>();
	protected int x, y, absX, absY, width, height, id;
	protected boolean visible = false;

	Component(int id, int x, int y, int width, int height) {
		this.id = id;
		this.x = x;
		this.y = y;
		absX = x;
		absY = y;
		this.width = width;
		this.height = height;
	}
	
	Component(int id, int width, int height) { 
		this(id, 0, 0, width, height);
	}
	
	public Action getAction(ActionType event) {
		return actionEvents.get(event);
	}
	
	public void putAction(ActionType event, Action action) {
		actionEvents.put(event, action);
	}
	
	public boolean getVisible() {
		return visible;
	}
	
	public void setVisible(boolean visible) {
		this.visible = visible;
		for (Component child : children) {
			child.setVisible(visible);
		}
		if (parent != null)
			parent.positionChildren();
	}

	public void setLocation(int x, int y) {
		this.x = x;
		this.y = y;
		updateAbsoluteLocation();
	}

	public Point getLocation() {
		Point location = new Point(x, y);
		return location;
	}

	public void setAbsoluteLocation(int abs_x, int abs_y) {
		this.absX = abs_x;
		this.absY = abs_y;
		for (Component child : children) {
			child.setAbsoluteLocation(this.absX + child.x, this.absY + child.y);
		}
	}

	public void updateAbsoluteLocation() {
		if (parent != null)
			setAbsoluteLocation(parent.absX + x, parent.absY + y);
		else
			setAbsoluteLocation(x, y);
	}

	public void setSize(int width, int height) {
		this.width = width;
		this.height = height;
		if (parent != null)
			parent.positionChildren();
	}

	public Component getParent() {
		return parent;
	}

	public boolean handleAction(ActionType actionType, int x, int y) {
		if(!visible) {
			return false;
		}
		if (contains(x, y)) {
			Action action = getAction(actionType == ActionType.MOUSE_MOVE ? ActionType.MOUSE_ENTER : actionType);
			if (action != null) {
				action.doAction(x, y);
				return true;
			}
			for (Component child : children) {
				if(child.handleAction(actionType, x, y)) {
					return true;
				}
			}
		} else if(actionType == ActionType.MOUSE_MOVE) {
			Action action = getAction(ActionType.MOUSE_EXIT);
			if (action != null) {
				action.doAction(x, y);
				return true;
			}
			for (Component child : children) {
				if(child.handleAction(actionType, x, y)) {
					return true;
				}
			}
		}
		return false;
	}
	
	public void draw(Graphics g) { 
		if (!getVisible()) {
			return;
		}
		drawComponent(g);
		for (Component child : children) {
			child.draw(g);
		}
	}
	
	abstract void drawComponent(Graphics g);
}
